<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        body{
            overflow: hidden;
            background-color: #222;
        }
        .box{
            position:absolute;
            display: block;
            width:300px;
            height:4px;
            border-radius:4px;
            transform:rotate(-30deg);
            background-image: linear-gradient(to right,#fff 25%,transparent  80%,#222 100%);
        }
        .box::before,
        .box::after{
            position: absolute;
            display: block;
            content: "";
            width: inherit;
            height: inherit;
            background-image:inherit;
        }
        .box::before{
            filter: blur(10px);
        }
        .box::after{
            filter: blur(10px);
        }
    </style>
</head>
<body>
<script>

    //抽象出一个专门生成小球的构造函数Ball
    class Ball{
        constructor() { //构造器

            //创建一个小球，即构造函数Ball实例出一个实例对象小球ball
            this.color = "#" + Math.random().toString(16).slice(2,8)
            this.ball = Ball.init(this.color) //静态方法不能被实例对象小球ball调用，就只能用构造函数Ball直接访问，将随机颜色作为参数传入
            //这里Ball访问init方法就会生成并返回一个小球元素节点，我们用this.ball来接收返回的这个元素，方便后续操作生成的小球

            //小球的初始位置坐标
            this.startPoint = {
                x:Math.random() * 2000, //x坐标
                y:Math.random() * 60 //y坐标
            }

            //小球的运动时间
            this.duration = 5000 * Math.random() + 5000

            //小球的结束位置坐标
            //this.endPoint = {
            //    x:Math.random() * 2000 - 2500,
            //    y:Math.random() * 2000 + 1000
            //}

            //小球的当前位置坐标
            this.currentPoint = {
                x:this.startPoint.x,
                y:this.startPoint.y
            }

            //小球的运动速度
            //v = （s1 - s0） / t   元素的运动速度 = （结束位置 - 初始位置） / 运动时间
            //this.speed = {
            //    x:(this.endPoint.x - this.startPoint.x) / this.duration,
            //    y:(this.endPoint.y - this.startPoint.y) / this.duration
            //}

            //小球的运动速率
            let sv = 0.2 * Math.random() + 0.4
            this.speed = { //让每次移动的x和y都相等，才不显得生硬奇怪
                vx:-sv,
                vy:sv
            }

            //先强行绑定小球不停运动渲染时this.animation的this指向
            this.animation = this.animation.bind(this) //react的this指向问题的解决方法

            //进行第一次渲染，让小球出现在它的开始位置
            this.render(this.startPoint) //render方法执行，渲染出小球
        }

        //抽象出创建小球的init方法，不想被别人调用，使用静态方法static
        static init(color){ //接收一个形参color
            let div = document.createElement("div") //createElement方法会创建并返回一个div标签元素节点，这个div标签元素节点就是小球
            div.className = "box" //div标签元素节点的类名叫box
            div.style.backgroundColor = color //给这个div标签元素节点设置背景颜色
            document.body.appendChild(div) //将创建的div标签元素节点小球添加到页面中的body标签元素当中
            return div //将这个div标签元素节点小球返回出去，只有返回出去才能被外部访问并操作小球
        }

        //抽象出小球的渲染函数render 只需要渲染开始位置就可以 传入什么渲染什么
        render(point){
            this.ball.style.left = point.x + "px"
            this.ball.style.top = point.y + "px"
        }

        //抽象出小球开始运动
        start(){ //一旦执行start就表示运动开始

            //获取开始运动的时间
            this.startTime = new Date()

            //不停地开始渲染动画
            this.animation()
        }

        //记录时间的渲染动画函数
        animation(){

            //获取现在的时间
            let current = new Date()

            if(current - this.startTime > this.duration) { //如果现在的时间-开始运动的时间>小球运动的时间，就停止渲染动画

                //清除这个小球
                document.body.removeChild(this.ball)

                return
            }

            //下面就是真正运动的描述
            requestAnimationFrame(this.animation)

            //就可以计算当前的位置 sx = s0 + (tx - t0) * v
            //元素这一时刻的位置 = 初始位置 + （任意时刻 - 开始运动的时刻）* 元素的运动速度
            this.currentPoint.x = this.startPoint.x + (current - this.startTime) * this.speed.vx
            this.currentPoint.y = this.startPoint.y + (current - this.startTime) * this.speed.vy

            //执行render
            this.render(this.currentPoint)
        }
    }

    let timer = setInterval(() => {
        let ball = new Ball()
        ball.start()
        ball = new Ball()
        ball.start()
    },500)

</script>
</body>
</html>